package com.study.studyroom.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.study.studyroom.entity.bo.OptionBo;
import com.study.studyroom.entity.bo.UserBo;
import com.study.studyroom.entity.domain.User;
import com.study.studyroom.entity.enums.RequestResultEnum;
import com.study.studyroom.entity.exception.GlobalException;
import com.study.studyroom.entity.vo.Condition;
import com.study.studyroom.entity.vo.user.LoginVo;
import com.study.studyroom.entity.vo.user.RegisterVo;
import com.study.studyroom.entity.vo.user.UserVo;
import com.study.studyroom.mapper.UserMapper;
import com.study.studyroom.service.UserService;
import com.study.studyroom.utils.TokenUtil;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Service
@AllArgsConstructor
public class UserServiceImpl extends BaseService implements UserService {
    private final UserMapper userMapper;

    /**
     * 登录功能
     * @param loginVo 登录数据
     * @return 登陆结果
     */
    @Override
    public String userLogin(LoginVo loginVo) {
        loginVo.checkParam();
        String account = loginVo.getAccount();
        String password = generatePassword(loginVo.getPassword());
        int userType = loginVo.getUserType();
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getDeleteFlag, false)
                .eq(User::getAccount, account)
                .eq(User::getPassword, password)
                .eq(User::getUserType,userType);
        User user = userMapper.selectOne(queryWrapper);
        if (user==null){
            throw new GlobalException(RequestResultEnum.NO_USER_OR_PASSWORD_ERROR);
        }
        if (Objects.equals(user.getDataStatus(),false)){
            throw new GlobalException(RequestResultEnum.USER_DISABLED);
        }
        return TokenUtil.generateToken(String.valueOf(userType),String.valueOf( user.getId()));
    }

    @Override
    public int userRegister(RegisterVo registerVo) {
        registerVo.checkParam();
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getDeleteFlag,false)
                .eq(User::getAccount,registerVo.getAccount());
        List<User> users = userMapper.selectList(queryWrapper);
        if (CollectionUtils.isNotEmpty(users)){
            throw new GlobalException(RequestResultEnum.USER_EXIST);
        }
        User user = new User();
        BeanUtils.copyProperties(registerVo,user);
        user.setId((int) System.currentTimeMillis());
        user.setBalance(new BigDecimal(0));
        user.setPassword(this.generatePassword(user.getPassword()));
        return this.insert(userMapper,user);
    }

    @Override
    public User getUserInfoById(Integer id) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getDeleteFlag, false)
                .eq(User::getDataStatus,true)
                .eq(User::getId,id);
        User user = userMapper.selectOne(queryWrapper);
        if(user==null){
            throw new GlobalException(RequestResultEnum.USER_DISABLED_OR_NOT_EXISTS);
        }
        return user;
    }

    @Override
    public UserBo updateUserInfo(UserVo userVo) {
        User oldUser= this.selectById(userMapper,userVo.getId());
        User newUser = this.getUser(userVo);
        oldUser = this.update(userMapper,newUser,oldUser);
        return this.getUserBo(oldUser);
    }

    @Override
    public UserBo updateUserStatus(User user) {
        user =  this.selectById(userMapper,user.getId());
        user = this.updateDataStatusById(userMapper,user);
        return this.getUserBo(user);
    }

    @Override
    public IPage<UserBo> getUserInfo(Condition<UserVo> userCondition) {
        Page<User> page = Page.of(userCondition.getPageIndex(), userCondition.getPageSize());
        UserVo userVo = userCondition.getQueryInfo()==null?new UserVo():userCondition.getQueryInfo();
        LambdaQueryWrapper<User> queryWrapper = getQueryWrapper(userVo);
        Page<User> userPage = userMapper.selectPage(page, queryWrapper);
        Page<UserBo> result = new Page<>();
        result.setRecords(new ArrayList<>());
        result.setTotal(userPage.getTotal());
        for (User record : userPage.getRecords()) {
            result.getRecords().add(this.getUserBo(record));
        }
        return result;
    }

    @Override
    public Integer deleteUser(User user) {
        return this.deleteById(userMapper, user);
    }

    @Override
    public List<OptionBo> getUserByName(String name) {
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(name)){
            userLambdaQueryWrapper.like(User::getUserName,name);
        }
        List<User> users = userMapper.selectList(userLambdaQueryWrapper);
        List<OptionBo> result = new ArrayList<>();
        for (User user : users) {
            result.add(new OptionBo(user.getId(),user.getUserName()));
        }
        return result;
    }

    @Override
    public User getUserInfoByToken(String token) {
        if (StringUtils.isBlank(token)) {
            throw new GlobalException(RequestResultEnum.CUSTOM_PARAM_CHECK_FAILED);
        }
        String userId = TokenUtil.getUserIdByToken(token);
        return selectById(userMapper,Integer.parseInt(userId));
    }

    @Override
    public Boolean resetPassword(String id,String password) {
        if (StringUtils.isBlank(password)){
            throw new GlobalException(RequestResultEnum.CUSTOM_PARAM_CHECK_FAILED);
        }
       User user= this.selectById(userMapper, Integer.parseInt(id));
       user.setPassword(generatePassword(password));
       return userMapper.updateById(user)==1;
    }

    @Override
    public Boolean addBalance(String id, BigDecimal price) {
        if (price==null){
            throw new GlobalException(RequestResultEnum.CUSTOM_PARAM_CHECK_FAILED);
        }
        User user= this.selectById(userMapper, Integer.parseInt(id));
        user.setBalance(user.getBalance().add(price));
        return userMapper.updateById(user)==1;
    }

    /**
     * 密码md5加密
     * @param password 原密码
     * @return 加密后密码
     */
    private String generatePassword(String password){
        return DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8));
    }

    private User getUser(UserVo userVo){
        User user = new User();
        BeanUtils.copyProperties(userVo,user);
        return user;
    }
    private UserBo getUserBo(User user){
        UserBo userBo = new UserBo();
        BeanUtils.copyProperties(user,userBo);
        return userBo;
    }
    private LambdaQueryWrapper<User> getQueryWrapper(UserVo userVo){
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getDeleteFlag,false);
        if (userVo!=null){
            if (StringUtils.isNotBlank(userVo.getAccount())){
                queryWrapper.like(User::getAccount,userVo.getAccount());
            }
            if (StringUtils.isNotBlank(userVo.getUserName())){
                queryWrapper.eq(User::getUserName,userVo.getUserName());
            }
            if (userVo.getUserType()!=0){
                queryWrapper.eq(User::getUserType,userVo.getUserType());
            }
            if (userVo.getDataStatus()!=null){
                queryWrapper.eq(User::getDataStatus,userVo.getDataStatus());
            }
        }
        return queryWrapper;
    }
}
